//@author A0096759E

package logic;

import java.util.Stack;

import storage.ScheduleEvent;
import storage.Storage;
import storage.UndoRedoStackEntry;
import applogger.AppLogger;

public class ScheduleRedoer {
	
	private static final String ADD_COMMAND = "add";
	private static final String DELETE_COMMAND = "del";
	private static final String CLEAR_COMMAND = "clr";
	private static final String MARK_DONE_COMMAND = "done";
	private static final String MARK_UNDONE_COMMAND = "undone";
	private static final String MODIFY_COMMAND = "mod";
	
	private static final String SUCCESS_MSG_REDO_MOD = "Successfully modified Event!";
	private static final String ERROR_MSG_CANNOT_REDO = "Unable to redo! No undone command found!";
	
	private Storage eventsList;
	private Stack<UndoRedoStackEntry> redoStack;

	/**
	 * Constructor for ScheduleRedoer. Takes in the current LifeShelf storage.
	 * @param eventsList
	 */
	public ScheduleRedoer(Storage eventsList) {
		this.eventsList = eventsList;
		this.redoStack = eventsList.getRedoStack();
	}
	
	/**
	 * Looks at the redo stack. Decodes it and calls the respective methods to redo the action
	 * @return
	 */
	public String redoLast() {
		if (redoStack.empty()) return ERROR_MSG_CANNOT_REDO; 
		String lastUndoneCommand = redoStack.peek().getCommand();
		switch (lastUndoneCommand) {
		case ADD_COMMAND:
			return redoLastDelete();
		case DELETE_COMMAND:
			return redoLastAdd();
		case CLEAR_COMMAND:
			return redoLastClear();
		case MARK_DONE_COMMAND:
			return redoLastMarkUndone();
		case MARK_UNDONE_COMMAND:
			return redoLastMarkDone();
		case MODIFY_COMMAND:
			return redoLastModify();
		}
		return ERROR_MSG_CANNOT_REDO;
	}

	/**
	 * Redoes the last delete command
	 * @return a success message if done, or error message if not
	 */
	private String redoLastDelete() {
		AppLogger.log("Redoing Last Delete");
		ScheduleEvent lastAdded = redoStack.pop().getEvent();
		eventsList.getUndoStack().push(new UndoRedoStackEntry(DELETE_COMMAND, lastAdded));
		return eventsList.deleteEvent(eventsList.getEventIndex(lastAdded)+1);
	}
	
	/**
	 * Redoes the last add command
	 * @return a success message if done, or error message if not
	 */
	private String redoLastAdd() {
		AppLogger.log("Redoing Last Add");
		ScheduleEvent lastDeleted = redoStack.pop().getEvent();
		eventsList.getUndoStack().push(new UndoRedoStackEntry(ADD_COMMAND, lastDeleted));
		return eventsList.addEvent(lastDeleted);
	}	
	
	/**
	 * Redoes the last clear command
	 * @return a success message if done, or error message if not
	 */
	private String redoLastClear() {
		AppLogger.log("Redoing Last Clear");
		redoStack.pop().getEvent();
		return eventsList.clearAllEvents();
	}
	
	/**
	 * Redoes the last modify command
	 * @return a success message if done, or error message if not
	 */
	private String redoLastModify() {
		AppLogger.log("Redoing Last Modify");
		redoStack.pop();
		redoLastDelete();
		redoStack.peek().getEvent().setGoogleUID(null);
		redoLastAdd();
		eventsList.getUndoStack().push(new UndoRedoStackEntry(MODIFY_COMMAND, null));
		return SUCCESS_MSG_REDO_MOD;
	}
	
	/**
	 * Redoes the last mark command
	 * @return a success message if done, or error message if not
	 */
	private String redoLastMarkDone() {
		AppLogger.log("Redoing Last Mark Done");
		ScheduleEvent lastMarked = redoStack.pop().getEvent();
		eventsList.getUndoStack().push(new UndoRedoStackEntry(MARK_DONE_COMMAND, lastMarked));
		return eventsList.markEventDone(eventsList.getEventIndex(lastMarked)+1);
	}
	
	/**
	 * Redoes the last unmark command
	 * @return a success message if done, or error message if not
	 */
	private String redoLastMarkUndone() {
		AppLogger.log("Redoing Last Mark Not Done");
		ScheduleEvent lastUnmarked = redoStack.pop().getEvent();
		eventsList.getUndoStack().push(new UndoRedoStackEntry(MARK_UNDONE_COMMAND, lastUnmarked));
		return eventsList.markEventUndone(eventsList.getEventIndex(lastUnmarked)+1);
	}
}
